// 2025/7/18: 首个版本

using System;
using System.Collections.Generic;
using Python.Runtime;
using ASEva;
using ASEva.Utility;

namespace CommonSource;

// 需要库文件并在csproj中引用：Python.Runtime.dll
// 需要启用Python支持插件，并在本插件的Plugin.OnApplicationStarted函数中调用SystemPythonRunner.Enable()
// 仅限在主机端运行

class SystemPythonRunner
{
    public static void Enable()
    {
        if (AgencyLocal.ClientSide) return;
        AgencyLocal.SetGlobalVariable("Python.ExternalUseFlag", "");
    }

    public static Dictionary<String, object> Run(String script, Dictionary<String, object> inputValues, String[] outputNames)
    {
        if (AgencyLocal.ClientSide) return null;
        if (AgencyLocal.GetGlobalVariable("Python.IsExternalUseAvailable", "no") != "yes") return null;

        try
        {
            using (Py.GIL())
            {
                var scope = Py.CreateScope();
                foreach (var pair in inputValues)
                {
                    scope.Set(pair.Key, pair.Value == null ? Runtime.None : pair.Value.ToPython());
                }

                scope.Exec(script);
                
                var outputValues = new Dictionary<String, object>();
                foreach (var name in outputNames)
                {
                    if (scope.Contains(name))
                    {
                        outputValues[name] = scope.Get(name).AsManagedObject(typeof(object));
                    }
                    else
                    {
                        outputValues[name] = null;
                    }
                }

                return outputValues;
            }
        }
        catch (Exception ex)
        {
            Dump.Exception(ex);
            return null;
        }
    }

    public static void RunTest()
    {
        var t0 = DateTime.Now;
        var outputValues = SystemPythonRunner.Run(testScript,
            inputValues: new()
            {
                ["text"] = "Hello world",
                ["number"] = 5.5,
                ["multiply"] = true,
            },
            outputNames:
            [
                "output"
            ]);
        var costTime = (DateTime.Now - t0).TotalMilliseconds;
        if (outputValues != null) AgencyLocal.Print("output=" + outputValues["output"] + " costTime=" + costTime + "ms");
    }

private static String testScript = @"
text_length = len(text)
if multiply:
    output = text_length * number
else:
    output = text_length + number";
}